/*
==========================未经授权，转载需保留此信息============================
Function : Operation for cc1101
Taobao website:http://zeyaotech.taobao.com/
Official website:http://www.ashining.com/
Written by:Lijian
TEL:028-64891123(Sales),028-64891129(Technology),e-mail: service@ashining.com
================================================================================
*/

/*
================================================================================
Description : This module contains the low level operations for CC1101
================================================================================
*/
#include "CC1101.H"
#include "CC1101_REG.h"
#include "string.h"//use "memcpy"

//*****更多功率参数设置可详细参考DATACC1100英文文档中第48-49页的参数表**********
//uint8 PaTabel[8] = {0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04};  //-30dBm   功率最小
//uint8 PaTabel[8] = {0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60}; //0dBm
uint8 PaTabel[8] = {0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0};   //10dBm     功率最大
uint8 tx[50];
uint8 rxBuffer[50];


// RF output power = 0 dBm
// RX filterbandwidth = 540.000000 kHz
// Deviation = 0.000000
// Datarate = 250.000000 kbps
// Modulation = (7) GFSK
// Manchester enable = (0) Manchester disabled
// RF Frequency = 433.000000 MHz
// Channel spacing = 199.951172 kHz
// Channel number = 0
// Optimization = Sensitivity
// Sync mode = (3) 30/32 sync word bits detected
// Format of RX/TX data = (0) Normal mode, use FIFOs for RX and TX
// CRC operation = (1) CRC calculation in TX and CRC check in RX enabled
// Forward Error Correction = (0) FEC disabled
// Length configuration = (1) Variable length packets, packet length configured by the first received byte after sync word.
// Packetlength = 255
// Preamble count = (2) 4 bytes
// Append status = 1
// Address check = (11) No address check
// FIFO autoflush = 0
// Device address = 0
// GDO0 signal selection = ( 6)
// GDO2 signal selection = (11) Serial Clock
const RF_SETTINGS rfSettings = {
    0x06,  // IOCFG0        GDO0 Output Pin Configuration
    0x05,  // PKTCTRL0      Packet Automation Control
    0x0C,  // FSCTRL1       Frequency Synthesizer Control
    0x10,  // FREQ2         Frequency Control Word, High Byte
    0xA7,  // FREQ1         Frequency Control Word, Middle Byte
    0x62,  // FREQ0         Frequency Control Word, Low Byte
    0x2D,  // MDMCFG4       Modem Configuration
    0x3B,  // MDMCFG3       Modem Configuration
    0x13,  // MDMCFG2       Modem Configuration
    0x62,  // DEVIATN       Modem Deviation Setting
    0x18,  // MCSM0         Main Radio Control State Machine Configuration
    0x1D,  // FOCCFG        Frequency Offset Compensation Configuration
    0x1C,  // BSCFG         Bit Synchronization Configuration
    0xC7,  // AGCCTRL2      AGC Control
    0x00,  // AGCCTRL1      AGC Control
    0xB0,  // AGCCTRL0      AGC Control
    0xFB,  // WORCTRL       Wake On Radio Control
    0xB6,  // FREND1        Front End RX Configuration
    0xEA,  // FSCAL3        Frequency Synthesizer Calibration
    0x2A,  // FSCAL2        Frequency Synthesizer Calibration
    0x00,  // FSCAL1        Frequency Synthesizer Calibration
    0x1F,  // FSCAL0        Frequency Synthesizer Calibration
    0x09,  // TEST0         Various Test Settings

    0x59, // FSTEST Frequency synthesizer calibration.
    0x88, // TEST2 Various test settings.
    0x31, // TEST1 Various test settings.
    0x02, // IOCFG2 GDO2 output pin configuration.
    0x04, // PKTCTRL1 Packet automation control.
    0x12, // ADDR Device address.
    0x32, // PKTLEN Packet length.
    0x00, // FSCTRL0 Frequency synthesizer control.
    0x22, // MDMCFG1 Modem configuration.
    0xF8, // MDMCFG0 Modem configuration.
    50,   // CHANNR Channel number.
    0x10, // FREND0 Front end RX configuration.
    0x00,
};

void CC1101PowerReset(void)
{

    while (CC_CSN_IS_OFF() == 0);
    CC_CSN_SELECT_ON();
    CC_delay(10);
    CC_CSN_SELECT_OFF();
    CC_delay(41);
    CC_CSN_SELECT_ON();
    while ( CC_MI_IS_HIGH() );//waite SO =0
    SPI_ExchangeByte( CCxxx0_SRES );
    while ( CC_MI_IS_HIGH() );//waite SO =0 again
    CC_CSN_SELECT_OFF();
}

uint8 halSpiStrobe( uint8 addr )
{
    uint8 statusByte;

    while((addr < 0x30) || (addr > 0x3D));
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI() );
    statusByte = SPI_ExchangeByte(addr);		//写入命令
    CC_CSN_SELECT_OFF();
    return statusByte;
}

uint8 halSpiReadReg( uint8 addr )
{
    uint8 value;
    while(addr > 0x3B);
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI() );
    SPI_ExchangeByte( addr | CCxxx0_READ_BIT | CCxxx0_BURST_BIT );
    value = SPI_ExchangeByte( CCxxx0_Dummy_Byte );
    CC_CSN_SELECT_OFF();
    return value;
}

void halSpiWriteReg( uint8 addr, uint8 value )
{
    while((addr > 0x2E) && (addr != 0x3E));
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI() );
    SPI_ExchangeByte( addr );		//写地址
    SPI_ExchangeByte( value );		//写入配置
    CC_CSN_SELECT_OFF();
}

void halSpiWriteBurstReg( uint8 *buffer, uint8 count )
{
    uint8 i;
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI() );
    SPI_ExchangeByte( CCxxx0_TXFIFO | CCxxx0_BURST_BIT );
    for (i = 0; i < count; i++)
    {
        SPI_ExchangeByte( buffer[i] );
    }
    CC_CSN_SELECT_OFF();
}

void halSpiReadBurstReg( uint8 *buffer, uint8 count )
{
    uint8 i;
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI() );
    SPI_ExchangeByte( CCxxx0_RXFIFO | CCxxx0_BURST_BIT | CCxxx0_READ_BIT );
    for (i = 0; i < count; i++)
    {
        buffer[i] = SPI_ExchangeByte(0);
    }
    CC_CSN_SELECT_OFF();
}

void halSpiSetRFPwr( uint8 *buffer, uint8 count )
{
    uint8 i;
    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();
    while ( CC_READ_MI()  );
    SPI_ExchangeByte( CCxxx0_PA_TABLE0 | CCxxx0_BURST_BIT );
    for (i = 0; i < count; i++)
    {
        SPI_ExchangeByte( buffer[i] );
    }
    CC_CSN_SELECT_OFF();
}

void halRfWriteRfSettings(void)
{
    halSpiWriteReg(CCxxx0_FSCTRL1,  rfSettings.FSCTRL1);
    halSpiWriteReg(CCxxx0_FREQ2,    rfSettings.FREQ2);
    halSpiWriteReg(CCxxx0_FREQ1,    rfSettings.FREQ1);
    halSpiWriteReg(CCxxx0_FREQ0,    rfSettings.FREQ0);
    halSpiWriteReg(CCxxx0_MDMCFG4,  rfSettings.MDMCFG4);
    halSpiWriteReg(CCxxx0_MDMCFG3,  rfSettings.MDMCFG3);
    halSpiWriteReg(CCxxx0_MDMCFG2,  rfSettings.MDMCFG2);
    halSpiWriteReg(CCxxx0_CHANNR,   rfSettings.CHANNR);
    halSpiWriteReg(CCxxx0_DEVIATN,  rfSettings.DEVIATN);
    halSpiWriteReg(CCxxx0_FREND1,   rfSettings.FREND1);
    halSpiWriteReg(CCxxx0_MCSM0,    rfSettings.MCSM0);
    halSpiWriteReg(CCxxx0_FOCCFG,   rfSettings.FOCCFG);
    halSpiWriteReg(CCxxx0_BSCFG,    rfSettings.BSCFG);
    halSpiWriteReg(CCxxx0_AGCCTRL2, rfSettings.AGCCTRL2);
    halSpiWriteReg(CCxxx0_AGCCTRL1, rfSettings.AGCCTRL1);	//
    halSpiWriteReg(CCxxx0_AGCCTRL0, rfSettings.AGCCTRL0);
    halSpiWriteReg(CCxxx0_FSCAL3,   rfSettings.FSCAL3);
    halSpiWriteReg(CCxxx0_FSCAL2,   rfSettings.FSCAL2);
    halSpiWriteReg(CCxxx0_FSCAL1,   rfSettings.FSCAL1);  ///
    halSpiWriteReg(CCxxx0_FSCAL0,   rfSettings.FSCAL0);
    halSpiWriteReg(CCxxx0_TEST0,    rfSettings.TEST0);
    halSpiWriteReg(CCxxx0_IOCFG2,   rfSettings.IOCFG2);
    halSpiWriteReg(CCxxx0_IOCFG0,   rfSettings.IOCFG0);
    halSpiWriteReg(CCxxx0_PKTCTRL0, rfSettings.PKTCTRL0);
    halSpiWriteReg(CCxxx0_ADDR,     rfSettings.ADDR);
    halSpiWriteReg(CCxxx0_PKTLEN,   rfSettings.PKTLEN);
}

uint8 sendTxBufCmd( uint8 *pucData, uint16 usLength, TX_DATA_MODE mode )
{
    halSpiWriteBurstReg( pucData, (usLength) );

    halSpiStrobe( CCxxx0_STX );

    while( !CC_GDO0_IS_HIGH() );
    while( CC_GDO0_IS_HIGH() );

    {
        uint8 ucstate;
        ucstate = halSpiReadReg(CCxxx0_MARCSTATE);

    }
    halSpiStrobe( CCxxx0_SFTX );
    {
        uint8 ucstate;
        ucstate = halSpiReadReg(CCxxx0_MARCSTATE);
    }
    return 0;
}

uint8 halRfReceivePacket(uint8 *rxBuffer, uint8 *length)
{
    uint8 status[2];
    uint8 packetLength;
    uint8 i = ( *(length) * 4 );


    halSpiStrobe( CCxxx0_SRX );
//    CC_delay(2);
        {
            uint16 usDelayForRev = 3000;

            while( usDelayForRev-- ) {
                if(CC_GDO0_IS_HIGH()) {
                    while( CC_GDO0_IS_HIGH() );
                    break;
                }
                CC_delay(1);
                            }
        }

//    CC_delay(3000);
    if ((halSpiReadReg(CCxxx0_RXBYTES) & BYTES_IN_CCxxx0_RXFIFO)) {

        {
            uint8 ucRxByteVerify;
            ucRxByteVerify = halSpiReadReg(CCxxx0_RXBYTES);
            do {
                packetLength = ucRxByteVerify;
                ucRxByteVerify = halSpiReadReg(CCxxx0_RXBYTES);
            } while(packetLength != ucRxByteVerify);

        }

        halSpiReadBurstReg( &packetLength, 1 );

        if ( packetLength <= *length ) {

            halSpiReadBurstReg( rxBuffer, packetLength );
            *length = packetLength;

            halSpiReadBurstReg( status, 2 );
            halSpiStrobe( CCxxx0_SFRX );

            return ( status[1] & CCxxx0_CRC_OK );

        } else {

            *length = packetLength;
            halSpiStrobe( CCxxx0_SFRX );
            return 0;
        }

    } else
        return 0;

}

void CC_Init(void)
{
    CC_spiInit();
    CC1101PowerReset();
    halRfWriteRfSettings();
    CC1101SetSYNC(0x1239);
    setChannel(50);
    {
        halSpiReadReg(CCxxx0_CHANNR);
    }
    halSpiSetRFPwr(PaTabel, 8);
}

/*
================================================================================
Function : CC1101SetSYNC( )
    Set the SYNC bytes of the CC1101
INPUT    : sync, 16bit sync
OUTPUT   : None
================================================================================
*/
void CC1101SetSYNC( uint16 sync )
{
    halSpiWriteReg(CCxxx0_SYNC1, (0xFF & (uint8)( sync>>8 )) );
    halSpiWriteReg(CCxxx0_SYNC0, (0xFF & (uint8)sync) );
}

void setChannel(uint8 channel)
{
    halSpiWriteReg(CCxxx0_CHANNR, channel);
}

uint8 halReadRssi(void)
{
    return halSpiReadReg(CCxxx0_RSSI);
}

void CC1101SetIdle(void)
{
    halSpiStrobe(CCxxx0_SIDLE);
}

void CC1101SetPWD(void)
{
    halSpiStrobe(CCxxx0_SPWD);
}
